import { FindOptionsWhere, Repository } from 'typeorm';
import { Order, orderStatustype } from './models/order.entity';
import { Result } from '../../dto/result.type';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { GqlAuthGuard } from '../../guards/auth.guard';
import { OrderResult, OrderResults } from './dto/result-order.output';
import { PartialOrderInput } from './dto/order.input';
import { OrderType } from './dto/order.type';
import { OrderService } from './order.service';
import { CurUserId } from '../../decorators/current-user.decorator';
import { PageInput } from '../../dto/page.input';
import { ProductService } from '../product/product.service';
import { CardRecordService } from '../cardRecord/cardRecord.service';
import { InjectRepository } from '@nestjs/typeorm';
import { Product } from '../product/models/product.entity';
import { Organization } from '../organization/models/organization.entity';
import { CurOrgId } from '../../decorators/current-org.decorator';

@Resolver(() => OrderType)
@UseGuards(GqlAuthGuard)
export class OrderResolver {
  constructor(
    private readonly orderService: OrderService,
    private readonly productService: ProductService,
    private readonly cardRecordService: CardRecordService,
    @InjectRepository(Order)
    private orderRepository: Repository<Order>,
    @InjectRepository(Product)
    private productRepository: Repository<Product>,
    @InjectRepository(Organization)
    private organizationRepository: Repository<Organization>,
  ) {}

  @Query(() => OrderResult)
  async getorderInfo(
    @Args('orderCode') orderCode: string,
  ): Promise<{ data?: Order; message: string }> {
    const result = await this.orderService.findByCode(orderCode);
    if (result) {
      return {
        data: result,
        message: '获取成功',
      };
    }
    return {
      message: '获取失败',
    };
  }

  @Query(() => OrderResults)
  async getorderByProduct(
    @Args('productId') productId: string,
    @CurUserId() userId: string,
  ): Promise<{ data?: Order[]; message: string }> {
    const result = await this.orderService.findByProduct(productId, userId);
    if (result) {
      return {
        data: result.length === 0 ? null : result,
        message: '获取成功',
      };
    }
    return {
      message: '获取失败',
    };
  }

  @Mutation(() => Result)
  async commitorder(
    @Args('params') params: PartialOrderInput,
    @CurUserId() userId: string,
    @Args('orderCode', { nullable: true }) orderCode: string,
  ): Promise<Result> {
    if (!orderCode) {
      const product = await this.productService.findById(params.productId);
      const productSellNum = product.sellNum;
      const productStock = product.stock;
      // 创建用户个人消费卡
      const craeteCardRecordRes = await this.cardRecordService.addCardRecordw(
        params.productId,
        params.orgId,
        userId,
      );
      // 更新库存
      const updateProduct = await this.productService.updateById(
        params.productId,
        {
          sellNum: productSellNum + params.buyNum,
          stock: productStock - params.buyNum,
        },
      );
      // 创建订单
      const res = await this.orderService.create({
        ...params,
        userId,
        createdBy: userId,
        status: orderStatustype.PAYMENT_OVER,
      });
      return {
        message:
          res && updateProduct && craeteCardRecordRes ? '创建成功' : '创建失败',
        code: !!res && !!craeteCardRecordRes && !!updateProduct,
      };
    }
    const order = await this.orderService.findByCode(orderCode);
    if (order) {
      return await this.orderService.cancelOrder(orderCode);
    }
  }

  @Query(() => OrderResults)
  async getOrders(
    @CurUserId() userId: string,
    @Args('page') page: PageInput,
  ): Promise<{
    data: Order[];
    page: { total: number; pageSize: number; pageNum: number };
    message: string;
  }> {
    const { pageNum, pageSize } = page;
    const where: FindOptionsWhere<Order> = {
      createdBy: userId,
    };
    const [results, total] = await this.orderService.findOrders({
      start: pageNum === 1 ? 0 : (pageNum - 1) * pageSize,
      length: pageSize,
      where,
    });
    return {
      data: results,
      page: {
        pageNum,
        pageSize,
        total,
      },
      message: '获取成功',
    };
  }

  // 查询订单通过机构id
  @Query(() => OrderResults)
  async getOrdersByOrgId(
    @Args('page') page: PageInput,
    @Args('orgId') orgId: string,
  ): Promise<{
    data: Order[];
    page: { total: number; pageSize: number; pageNum: number };
    message: string;
  }> {
    const { pageNum, pageSize } = page;
    const where: FindOptionsWhere<Order> = {
      orgId,
    };
    const [results, total] = await this.orderService.findOrders({
      start: pageNum === 1 ? 0 : (pageNum - 1) * pageSize,
      length: pageSize,
      where,
    });
    return {
      data: results,
      page: {
        pageNum,
        pageSize,
        total,
      },
      message: '获取成功',
    };
  }

  @Mutation(() => Result)
  async deleteOrder(
    @Args('orderCode') orderCode: string,
    @CurUserId() userId: string,
  ): Promise<Result> {
    const result = await this.orderService.findByCode(orderCode);
    if (result) {
      const delRes = await this.orderService.delete(orderCode, userId);
      if (delRes) {
        return {
          message: '删除成功',
        };
      }
      return {
        message: '删除失败',
      };
    }
  }

  @Query(() => OrderResults)
  async getOrdersByUserId(
    @CurUserId() userId: string,
    @CurOrgId() orgId: string,
    @Args('transmitUserId', { nullable: true })
    transmitUserId: string | 'onlyOrg',
  ): Promise<{
    data: Order[];
    message: string;
  }> {
    const where = {
      createdBy: transmitUserId
        ? transmitUserId === 'onlyOrg'
          ? null
          : transmitUserId
        : userId,
      orgId,
    };
    const orders = await this.orderRepository.find({
      where,
      take: 9999,
      order: {
        buyTime: 'ASC',
      },
    });

    const productIds = [...new Set(orders.map((order) => order.productId))];
    const orgIds = [...new Set(orders.map((order) => order.orgId))];

    const [products, organizations] = await Promise.all([
      this.productRepository.findByIds(productIds),
      this.organizationRepository.findByIds(orgIds),
    ]);
    const productMap = new Map(
      products.map((product) => [product.id.toString(), product]),
    );
    const organizationMap = new Map(
      organizations.map((org) => [org.id.toString(), org]),
    );
    console.log(productMap, organizationMap);
    const results = orders.map((order) => {
      return {
        ...order,
        productName: productMap.get(order.productId)?.name,
        productLogo: productMap.get(order.productId)?.cover,
        productType: productMap.get(order.productId)?.type,
        orgName: organizationMap.get(order.orgId)?.name,
        orgLogo: organizationMap.get(order.orgId)?.logo,
      };
    }) as Order[];

    return {
      data: results,
      message: '获取成功',
    };
  }
}
